package com.aplink.generic.webservice;

import java.util.ArrayList;
import java.util.Iterator;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.text.TextUtils;

import com.aplink.generic.dictionary.GenericDictionary;
import com.aplink.generic.network.GenericFile;
import com.aplink.generic.pojo.ContentData;
import com.aplink.generic.pojo.GenericAttribute;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.ObjPropInfo;
import com.aplink.generic.util.BitmapUtis;

public class WebServiceParser {
	private volatile static WebServiceParser sInstance = null;

	public static WebServiceParser getInstance() {
		if (WebServiceParser.sInstance == null) {
			synchronized (WebServiceParser.class) {
				if (WebServiceParser.sInstance == null) {
					WebServiceParser.sInstance = new WebServiceParser();
				}
			}
		}
		return WebServiceParser.sInstance;
	}

	public DataResult parse(String data, final ContentData objPropCol,
	        final GenericObject passedValue) throws JSONException {
		if (data == null) {
			return null;
		}
		if (data.trim().startsWith("{")) {
			data = String.format("[%s]", data.trim());
		}
		final JSONArray jsonarray = new JSONArray(data);
		return this.parseJson(jsonarray, objPropCol, passedValue);
	}

	public DataResult parse(String data, final String tableName,
	        final ContentData objPropCol) throws JSONException {
		if (data == null) {
			return null;
		}
		if (data.trim().startsWith("{")) {
			data = String.format("[%s]", data.trim());
		}
		final JSONArray jsonarray = new JSONArray(data);
		if (objPropCol == null) {
			return this.parseJson(jsonarray, tableName);
		}
		return this.parseJson(jsonarray, objPropCol, null);
	}

	private DataResult parseJson(final JSONArray jsonArray,
	        final ContentData objPropCol,
	        final GenericDictionary<String, GenericAttribute> listValue)
	        throws JSONException {
		final DataResult dataResult = new DataResult();
		final ArrayList<GenericObject> genericObjects = new ArrayList<GenericObject>();
		for (int i = 0; i < jsonArray.length(); i++) {
			final JSONObject jsonResult = (JSONObject) jsonArray.get(i);
			if (jsonResult != null) {
				final ResponseStatus responseStatus = new ResponseStatus();
				if (jsonResult.has("Result")) {
					final int result = jsonResult.getInt("Result");
					responseStatus.setStatus(result);
				} else if (jsonResult.has("Description")) {
					final String description = jsonResult
					        .getString("Description");
					responseStatus.setDescription(description);
				} else {
					responseStatus.setStatus(ResponseStatus.SUCCESS);
				}
				dataResult.setResponseStatus(responseStatus);
				if (responseStatus.getStatus() == ResponseStatus.SUCCESS) {
					if (!objPropCol.isEmpty()) {
						final GenericObject genericObject = new GenericObject();
						genericObject.setTableName(objPropCol.getMainTable());
						String imageLocalPath = null;
						ObjPropInfo fileLocalPath = null;
						for (int j = 0; j < objPropCol.size(); j++) {
							final ObjPropInfo objPropInfo = objPropCol
							        .valueAt(j);
							final String name = objPropInfo.getFullColumnName();
							final String webserviceVariable = objPropCol
							        .getWebserviceParameter(objPropInfo);
							GenericAttribute attribute = null;
							if (!TextUtils.isEmpty(webserviceVariable)
							        && jsonResult.has(webserviceVariable)) {
								final String value = jsonResult.get(
								        webserviceVariable).toString();
								attribute = GenericAttribute.obtain(value,
								        objPropInfo);
								if (objPropInfo.isImageServerPath()) {
									if (!TextUtils.isEmpty(value)) {
										final GenericFile genericFile = BitmapUtis
										        .getInstance().download(value);
										if (genericFile != null) {
											imageLocalPath = genericFile
											        .getLocalPath();
										}
									}
								}
							} else if ((listValue != null)
							        && listValue.containsKey(name)) {
								String value = null;
								if ((listValue.get(name) != null)
								        && (listValue.get(name).getValue() != null)) {
									value = listValue.get(name).getValue()
									        .toString();
								}
								attribute = GenericAttribute.obtain(value,
								        objPropInfo);
							} else {
								attribute = GenericAttribute.obtain(null,
								        objPropInfo);
							}
							genericObject.put(name, attribute);
							if (objPropInfo.isImageLocalPath()) {
								fileLocalPath = objPropInfo;
							}
						}
						if (fileLocalPath != null) {
							genericObject.put(
							        fileLocalPath.getFullColumnName(),
							        imageLocalPath);
						}
						genericObjects.add(genericObject);
					}
				}
			}
		}
		dataResult.setData(genericObjects);
		return dataResult;
	}

	private DataResult parseJson(final JSONArray jsonArray,
	        final String tableName) throws JSONException {
		final ArrayList<GenericObject> genericObjects = new ArrayList<GenericObject>();
		final DataResult dataResult = new DataResult();
		for (int i = 0; i < jsonArray.length(); i++) {
			final JSONObject jsonObject = jsonArray.getJSONObject(i);
			final Iterator<?> keys = jsonObject.keys();
			if (jsonObject != null) {
				if (jsonObject.has("Result") && jsonObject.has("Description")) {
					final int result = jsonObject.getInt("Result");
					final String description = jsonObject
					        .getString("Description");
					final ResponseStatus responseStatus = new ResponseStatus();
					responseStatus.setDescription(description);
					responseStatus.setStatus(result);
					dataResult.setResponseStatus(responseStatus);
				}
				final GenericObject genericObject = new GenericObject();
				genericObject.setTableName(tableName);
				while (keys.hasNext()) {
					final String key = (String) keys.next();
					if (jsonObject.has(key)) {
						final String value = jsonObject.getString(key);
						final GenericAttribute attribute = new GenericAttribute(
						        key, value);
						genericObject.put(tableName + "." + key, attribute);
					}
				}
				genericObjects.add(genericObject);
			}
		}
		dataResult.setData(genericObjects);
		return dataResult;
	}
}
